<script setup lang="ts">
interface Props {
  value?: boolean
}

const props = defineProps<Props>()

const { toggleFeature, features, isEngineeringModeOn } = useBetaFeatureToggle()

const value = useVModel(props, 'value')

const { appInfo } = useGlobal()

const selectedFeatures = ref<Record<string, boolean>>({})

// Add search functionality
const searchQuery = ref('')

const isEnabledOnPremFeature = (feature: BetaFeatureType) => {
  if (appInfo.value.isOnPrem && feature.isOnPrem === false) return false

  return true
}

const isFeatureVisible = (feature: BetaFeatureType) => {
  return (!feature?.isEE || isEeUI) && (!feature?.isEngineering || isEngineeringModeOn.value) && isEnabledOnPremFeature(feature)
}

const filteredFeatures = computed(() => {
  if (!searchQuery.value) return features.value

  const query = searchQuery.value.toLowerCase()

  // Helper function to calculate match score
  const getMatchScore = (feature: BetaFeatureType) => {
    const title = feature.title.toLowerCase()
    const description = feature.description.toLowerCase()

    // Exact prefix match in title (highest priority)
    if (title.startsWith(query)) return 4
    // Contains exact match in title
    if (title.includes(query)) return 3
    // Exact prefix match in description
    if (description.startsWith(query)) return 2
    // Contains exact match in description
    if (description.includes(query)) return 1
    // No match
    return 0
  }

  return features.value
    .filter((feature) => {
      if (!isFeatureVisible(feature)) return false

      const title = feature.title.toLowerCase()
      const description = feature.description.toLowerCase()
      return title.includes(query) || description.includes(query)
    })
    .sort((a, b) => {
      const scoreA = getMatchScore(a)
      const scoreB = getMatchScore(b)
      return scoreB - scoreA
    })
})

const isAllFeaturesEnabled = computed({
  get: () => {
    return features.value.every((feature) => {
      return !isFeatureVisible(feature) || selectedFeatures.value[feature.id]
    })
  },
  set: (value: boolean) => {
    features.value.forEach((feature) => {
      if (isFeatureVisible(feature) && feature.enabled !== value) {
        if (toggleFeature(feature.id, value)) {
          selectedFeatures.value[feature.id] = value
        }
      }
    })
  },
})

const saveExperimentalFeatures = () => {
  features.value.forEach((feature) => {
    if (selectedFeatures.value[feature.id] !== feature.enabled) {
      toggleFeature(feature.id)
    }
  })
}

onMounted(() => {
  selectedFeatures.value = Object.fromEntries(features.value.map((feature) => [feature.id, feature.enabled]))
})

watch(value, (val) => {
  if (val) {
    selectedFeatures.value = Object.fromEntries(features.value.map((feature) => [feature.id, feature.enabled]))
  }
})

const clickCount = ref(0)
const clickTimer = ref<NodeJS.Timeout | undefined>(undefined)
const handleClick = () => {
  clickCount.value++

  if (clickCount.value === 1) {
    if (clickTimer.value) clearTimeout(clickTimer.value)
    clickTimer.value = setTimeout(() => {
      clickCount.value = 0
    }, 3000)
  }

  if (clickCount.value >= 3) {
    isEngineeringModeOn.value = !isEngineeringModeOn.value
    clickCount.value = 0
    if (clickTimer.value) {
      clearTimeout(clickTimer.value)
      clickTimer.value = undefined
    }
  }
}

useEventListener('keydown', (e: KeyboardEvent) => {
  if (isActiveInputElementExist()) return
  if (e.shiftKey && e.altKey && e.code === 'KeyE') {
    value.value = !value.value
  }
})

onUnmounted(() => {
  if (clickTimer.value) clearTimeout(clickTimer.value)
})
</script>

<template>
  <a-drawer
    v-model:visible="value"
    class="nc-features-drawer"
    :mask-style="{ background: 'transparent' }"
    width="min(32vw, 458px)"
    :closable="false"
  >
    <div class="flex flex-col h-full">
      <div class="flex items-center gap-3 px-2 !pl-4 border-b-1 h-[var(--toolbar-height)] flex-none border-nc-border-gray-medium">
        <component :is="iconMap.bulb" class="text-nc-content-inverted-secondary opacity-85 h-5 w-5" @click="handleClick" />
        <h1 class="text-base !text-nc-content-inverted-secondary font-weight-700 p-0 m-0">
          {{ $t('general.featurePreview') }}
        </h1>
        <nc-button type="text" class="!w-8 !h-8 !min-w-0 ml-auto" @click="value = false">
          <GeneralIcon icon="close" class="!text-nc-content-inverted-secondary" />
        </nc-button>
      </div>

      <div
        class="text-sm font-weight-500 text-nc-content-gray-subtle2 leading-5 m-4 mb-0 flex items-center justify-between gap-3 pr-3"
      >
        <span>
          {{ $t('labels.toggleExperimentalFeature') }}
        </span>
        <NcTooltip
          :title="
            isAllFeaturesEnabled
              ? `${$t('general.disable')} ${$t('general.all')}`
              : `${$t('general.enable')} ${$t('general.all')}`
          "
          class="flex"
        >
          <NcSwitch v-model:checked="isAllFeaturesEnabled" />
        </NcTooltip>
      </div>

      <div class="h-full overflow-y-auto nc-scrollbar-thin flex-grow p-4 !rounded-lg">
        <div ref="contentRef" class="!rounded-lg">
          <div class="sticky top-0 bg-nc-bg-default z-10 mb-2">
            <a-input v-model:value="searchQuery" type="text" placeholder="Search features..." class="nc-input-sm nc-input-shadow">
              <template #prefix>
                <GeneralIcon
                  :class="{
                    'text-nc-content-brand': searchQuery?.length,
                  }"
                  icon="search"
                  class="nc-search-icon h-3.5 w-3.5 mr-1"
                />
              </template>
            </a-input>
          </div>
          <div
            v-if="filteredFeatures?.length"
            class="border-1 !border-nc-border-gray-medium !rounded-lg max-h-[calc(100vh-200px)] overflow-y-auto nc-scrollbar-thin"
          >
            <div class="flex flex-col">
              <template v-for="feature in filteredFeatures" :key="feature.id">
                <div
                  v-if="isFeatureVisible(feature)"
                  class="border-b-1 px-3 flex gap-2 flex-col py-2 !border-nc-border-gray-medium last:border-b-0"
                >
                  <div class="flex items-center justify-between">
                    <div class="text-sm text-nc-content-gray !font-weight-600">
                      {{ feature.title }}
                    </div>
                    <NcSwitch v-model:checked="selectedFeatures[feature.id]" @change="saveExperimentalFeatures" />
                  </div>

                  <div class="text-nc-content-gray-muted leading-4 text-[13px] font-weight-500">
                    {{ feature.description }}
                  </div>
                </div>
              </template>
            </div>
          </div>
          <div v-else class="px-2 py-6 text-center text-nc-content-gray-muted flex flex-col items-center gap-6">
            <img
              src="~assets/img/placeholder/no-search-result-found.png"
              class="!w-[164px] flex-none"
              alt="No search results found"
            />

            {{ features?.length ? $t('title.noResultsMatchedYourSearch') : 'The list is empty' }}
          </div>
        </div>
      </div>
    </div>
  </a-drawer>
</template>

<style lang="scss">
.nc-features-drawer {
  .ant-drawer-content-wrapper {
    @apply !rounded-l-xl overflow-hidden mt-[48px] h-[calc(100vh_-_48px)];
    .ant-drawer-body {
      @apply p-0;
    }
  }
}

:deep(.field-list-with-search) {
  .nc-divider {
    display: none !important;
  }

  .nc-toolbar-dropdown-search-field-input {
    @apply rounded-lg;
  }

  .nc-list-item {
    @apply h-8 hover:bg-nc-bg-gray-light gap-x-1.5;
  }
}
</style>
